//****************************************************************************
//						mini_LVDS_out
//
//
//版本：v1.0		yshao		2021/04/27
//****************************************************************************
module mini_LVDS_out(
        //时钟 & 复位
        input   wire            resetb,
        input	wire			sclk,
        
		output	wire			out_rstb,
        
        //最终输出时序
        output	wire            clk2x,
        output	wire            dsync,
        input	wire			deout,
		input	wire	[47:0]	dout,

		//mini LVDS output
		output	wire	[1:0]	CLKOUT,
	    output	wire	[5:0]	DATAOUT,
		
        output  wire    [7:0]   tout
        );

//**************************************************************/
//              参数设置
//**************************************************************/

//**************************************************************/
//               信号定义
//**************************************************************/
//时钟&复位

wire			sysclk_locked;

//同步信号
reg		[1:0]	clk_div;

//复位码信号
reg		[7:0]	de_t;
reg		[47:0]	data_t[0:7];
reg		[47:0]	data_o;

//时钟域变换
(*keep*)reg	[7:0]	p00_d, p01_d, p02_d, p10_d, p11_d, p12_d;

//时钟域变换
reg		[7:0]	lan0_shift, lan1_shift,
				lan2_shift, lan3_shift,
				lan4_shift, lan5_shift;
//输出寄存器
(*keep*)wire	[3:0]	lan0_ddr_d, lan1_ddr_d,
				lan2_ddr_d, lan3_ddr_d,
				lan4_ddr_d, lan5_ddr_d;
				
//**************************************************************/
//               PLL
//**************************************************************/
//PLL模块
wire	clk_tx_4x_sft, clk4x90,clk4x_sft;

PLL_IP pll_out(
    .reset(~resetb),
    .refclk(sclk),
    
    .clk0_out(clk4x_sft),
    .clk1_out(clk4x90),
    .clk2_out(clk2x),
    .extlock(sysclk_locked)	
    );

assign	out_rstb = sysclk_locked ;
//************************************************/
//      同步信号
//************************************************/
//4分频
always @(posedge clk2x or negedge resetb)
	if (resetb == 0)
		clk_div <= 0;
	else
		clk_div <= clk_div + 1;

//并行时钟
assign	dsync = clk_div[0];

//************************************************/
//      添加复位码
//************************************************/
always @(posedge clk2x) 
	if (dsync == 1) begin
		de_t	<= {de_t[6:0], deout};
		data_t[0]	<= dout;
		data_t[1]	<= data_t[0];
		data_t[2]	<= data_t[1];
		data_t[3]	<= data_t[2];
		data_t[4]	<= data_t[3];
		data_t[5]	<= data_t[4];
		data_t[6]	<= data_t[5];
		data_t[7]	<= data_t[6];
		end
	
always @(posedge clk2x)
	if (dsync == 1) begin
		if ((deout == 1) && (de_t[5] == 0))
			data_o <= {24'hffffff, 24'hffffff};
		else if (de_t[6:5] == 2'b01)
			data_o <= {24'h9f9f9f, 24'h9f9f9f};
		else if (de_t[6] == 1)
			data_o <= data_t[6];
		else
			data_o <= 0;
	end

always @(posedge clk2x)
	if (dsync == 1) begin
		p00_d <= data_o[7:0];
		p01_d <= data_o[15:8];
		p02_d <= data_o[23:16];
		p10_d <= data_o[31:24];
		p11_d <= data_o[39:32];
		p12_d <= data_o[47:40];
	end

//************************************************/
//      时钟域转换
//************************************************/
always @(posedge clk2x)
	if (dsync == 1) begin
		lan0_shift <= p00_d;
		lan1_shift <= p01_d;
		lan2_shift <= p02_d;
		lan3_shift <= p10_d;
		lan4_shift <= p11_d;
		lan5_shift <= p12_d;
	end
	else begin
		lan0_shift <= lan0_shift[7:4];
		lan1_shift <= lan1_shift[7:4];
		lan2_shift <= lan2_shift[7:4];
		lan3_shift <= lan3_shift[7:4];
		lan4_shift <= lan4_shift[7:4];
		lan5_shift <= lan5_shift[7:4];
	end	    
        
assign	lan0_ddr_d = lan0_shift[3:0];
assign	lan1_ddr_d = lan1_shift[3:0];
assign	lan2_ddr_d = lan2_shift[3:0];
assign	lan3_ddr_d = lan3_shift[3:0];
assign	lan4_ddr_d = lan4_shift[3:0];
assign	lan5_ddr_d = lan5_shift[3:0];

//************************************************/
//      测试信号
//************************************************/
reg				de_ttt;
reg		[7:0]	de_count;
//reg		[3:0]	test_d;
reg				test_d;

always @(posedge clk2x)
	de_ttt <= deout;
	
always @(posedge clk2x)
	if (de_ttt == 0)
		de_count <= 0;
	else// if (de_count[7] == 0)
		de_count <= de_count + 1;
		
always @(posedge clk2x)
	if (de_ttt == 0)
		test_d <= 0;	
	else		
		test_d <= ~de_count[5];
//	else if (de_count == 15)
//		test_d <= 0;
//	else
//		test_d <= 1;
/* assign	lan0_ddr_d = {4{test_d}};
assign	lan1_ddr_d = {4{test_d}};
assign	lan2_ddr_d = {4{test_d}};
assign	lan3_ddr_d = ~{4{test_d}};
assign	lan4_ddr_d = ~{4{test_d}};
assign	lan5_ddr_d = ~{4{test_d}}; */


//************************************************/
//      DDR输出
//************************************************/
ODDR clkout0 ( .rst(1'b0 ), .clk( clk4x90 ), .d1( 1'b0 ), .d0( 1'b1 ), .q( CLKOUT[0] ) );
//ODDR clkout1 ( .rst(1'b0 ), .clk( clk4x90 ), .d1( 1'b1 ), .d0( 1'b0 ), .q( CLKOUT[1] ) );
ODDR clkout1 ( .rst(1'b0 ), .clk( clk4x90 ), .d1( 1'b0 ), .d0( 1'b1 ), .q( CLKOUT[1] ) );
//assign CLKOUT = {2{clk4x90}};
//assign DATAOUT = {6{test_d}};


ODDR2XK ODDRx2l_lan0(/*synthesis keep*/
	.q(DATAOUT[0]), 
	.pclk(clk2x), 
	.sclk(clk4x_sft), 
	.d3(lan0_ddr_d[3]), 
	.d2(lan0_ddr_d[2]), 
	.d1(lan0_ddr_d[1]), 
	.d0(lan0_ddr_d[0]), 
	.rst(1'b0)
);

ODDR2XK ODDRx2l_lan1(/*synthesis keep*/
	.q(DATAOUT[1]), 
	.pclk(clk2x), 
	.sclk(clk4x_sft), 
	.d3(lan1_ddr_d[3]), 
	.d2(lan1_ddr_d[2]), 
	.d1(lan1_ddr_d[1]), 
	.d0(lan1_ddr_d[0]), 
	.rst(1'b0)
);

ODDR2XK ODDRx2l_lan2(/*synthesis keep*/
	.q(DATAOUT[2]), 
	.pclk(clk2x), 
	.sclk(clk4x_sft), 
	.d3(lan2_ddr_d[3]), 
	.d2(lan2_ddr_d[2]), 
	.d1(lan2_ddr_d[1]), 
	.d0(lan2_ddr_d[0]), 
	.rst(1'b0)
);

ODDR2XK ODDRx2l_lan3(/*synthesis keep*/
	.q(DATAOUT[3]), 
	.pclk(clk2x), 
	.sclk(clk4x_sft), 
	.d3(lan3_ddr_d[3]), 
	.d2(lan3_ddr_d[2]), 
	.d1(lan3_ddr_d[1]), 
	.d0(lan3_ddr_d[0]), 
	.rst(1'b0)
);

ODDR2XK ODDRx2l_lan4(/*synthesis keep*/
	.q(DATAOUT[4]), 
	.pclk(clk2x), 
	.sclk(clk4x_sft), 
	.d3(lan4_ddr_d[3]), 
	.d2(lan4_ddr_d[2]), 
	.d1(lan4_ddr_d[1]), 
	.d0(lan4_ddr_d[0]), 
	.rst(1'b0)
);

ODDR2XK ODDRx2l_lan5(/*synthesis keep*/
	.q(DATAOUT[5]), 
	.pclk(clk2x), 
	.sclk(clk4x_sft), 
	.d3(lan5_ddr_d[3]), 
	.d2(lan5_ddr_d[2]), 
	.d1(lan5_ddr_d[1]), 
	.d0(lan5_ddr_d[0]), 
	.rst(1'b0)
);

//************************************************/
//      调试信号
//************************************************/
assign  tout = 0;

endmodule
